package org.dbp.error;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import org.apache.commons.lang3.StringUtils;
import org.dbp.error.exception.ExceptionDbp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * Se encarga de gestionar los mensajes de propiedades que vamos a usar. 
 * 
 * 	Nota: Esta clase normalmente en el api la vamos a utilizar para mostrar los mensajes de error.
 * 
 * 
 * @author dbp	
 *
 */
public class MensajeriaDbpUtils {

	protected static final String mensajeDeErrorNoExisteLaClave = "No se encontro un valor asociado a la clave [%s]";

	protected static final String mensajeDeErrorClaveVacia = "No podemos obtener un mensaje de una clave [%s] vacia o nula";

	private static final Logger logger = LoggerFactory.getLogger(MensajeriaDbpUtils.class);
	
	private static final MensajeriaDbpUtils instancia = new MensajeriaDbpUtils();
	
	private ResourceBundle resourceBundle;
	private Map<String,ResourceBundle> resources;

	
	public static MensajeriaDbpUtils obtenerInstancia(){
		return instancia;
	}
	
	
	
	public MensajeriaDbpUtils(){
		establecerResourceDefecto("dbpUtilsMensajeria");
		
		resources= new HashMap<String,ResourceBundle>();
		
	}
	/**
	 * 
	 * Se encarga de establecer el properties por defecto.
	 * 
	 * @param resource
	 */
	public void establecerResourceDefecto(String resource){
		resourceBundle = ResourceBundle.getBundle(resource);
	}
	/**
	 * Nota: Nos devuelve los datos, pero sin errores, para los test.
	 * @param clave
	 * @param obligatorio
	 * @param parametros
	 * @return
	 */
	public String obtenerMensajeMock(String clave,Boolean obligatorio,Object... parametros) {
		try {
			return obtenerMensaje(clave, obligatorio, parametros);
		} catch (ExceptionDbp e) {
			logger.debug("Error [{}]",e.getMessage(),e);
			return clave;
		}
	}
	/**
	 * 
	 * A traves de una clave nos devuelve un texto formateado.
	 * 
	 * @param clave			La clave del mensaje, en el properties.
	 * @param obligatorio	Si es verdadero, en caso de no existir la clave, devolvera un error. Si es falso, en caso de no existir nos devolvera la clave, como el valor.
	 * @param parametros	Los argumentos que vamos a asociar a la propiedad. Asocia por posici�n la parametro {0} a {1}.
	 * @return
	 * 
	 * 	Nos devuelve el testo asociado a la clase
	 * 
	 * @throws ExceptionDbp	
	 * 	<ul>
	 * 		<li>Si la clave es nula o vacia.</li>
	 * 		<li>Si es obligatoria la clave y no existe nos devuelve un error</li>
	 *  </ul>
	 */
	public String obtenerMensaje(String clave,Boolean obligatorio,Object... parametros) throws ExceptionDbp{
		return obtenerMensaje(null,clave, obligatorio, parametros);
	}


	/**
	 * 
	 * A traves de una clave nos devuelve un texto formateado.
	 * @param nombreResource	El nombre del recurso donde vamos a buscar el error
	 * @param clave			La clave del mensaje, en el properties.
	 * @param obligatorio	Si es verdadero, en caso de no existir la clave, devolvera un error. Si es falso, en caso de no existir nos devolvera la clave, como el valor.
	 * @param parametros	Los argumentos que vamos a asociar a la propiedad. Asocia por posici�n la parametro {0} a {1}.
	 * @return
	 * 
	 * 	Nos devuelve el testo asociado a la clase
	 * 
	 * @throws ExceptionDbp	
	 * 	<ul>
	 * 		<li>Si la clave es nula o vacia.</li>
	 * 		<li>Si es obligatoria la clave y no existe nos devuelve un error</li>
	 *  </ul>
	 */
	public String obtenerMensaje(String nombreResource,String clave,Boolean obligatorio,Object... parametros) throws ExceptionDbp{
		ResourceBundle resource = obtenerElResource(nombreResource);
		String valdev=null;
		if(StringUtils.isBlank(clave)){
			ErrorDbpUtils.obtenerInstancia().procesarError(logger
					 , String.format(mensajeDeErrorClaveVacia, clave));
		}else{
			Boolean encontroLaClave=false;
			try{
				valdev=resource.getString(clave);
				encontroLaClave=true;
			}catch(MissingResourceException e){
				logger.warn("No se ha encontrado la clave [{}]",clave);
				if(obligatorio){
					ErrorDbpUtils.obtenerInstancia().procesarError(logger
							,String.format(mensajeDeErrorNoExisteLaClave,clave));
				}else{
					valdev=clave;
				}
			}
			if(encontroLaClave){
				valdev = procesarLosArgumentos(valdev, parametros);
			}
		}
		return valdev;
	}
	/**
	 * 
	 * Se encarga de manetener el recurso
	 * 
	 * @param resource
	 * @return
	 */
	public ResourceBundle obtenerElResource(String resource) {
		ResourceBundle valdev=null;
		if(StringUtils.isBlank(resource)){
			valdev=resourceBundle;
		}else{
			if(!resources.containsKey(resource)){
				resources.put(resource, ResourceBundle.getBundle(resource));
				logger.info("Hemos creado el nuevo recurso [{}], para el tema de los recursos de los mensajes.",resource);
			}
			valdev=resources.get(resource);
		}
		return valdev;
	}
	/**
	 * Se encarga de procesar los parametros en un mensaje de testo. Usara el sistema de parametros {0}...{3}
	 * 
	 * @param valdev		El mensaje de texto
	 * @param parametros	Los parametros que vamos a trancribir, al mensaje.
	 * @return
	 */
	private String procesarLosArgumentos(String paramValdev, Object... parametros) {
		String valdev=paramValdev;
		if(parametros!=null && parametros.length>0){
			valdev=MessageFormat.format(valdev,parametros);
		}
		return valdev;
	}
	
}
